package org.infinitest;

import static java.awt.Color.*;

import static org.infinitest.ResultCollector.*;

import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import org.infinitest.swingui.HaltTestAction;
import org.infinitest.swingui.InfinitestView;
import org.infinitest.swingui.ReloadIndexAction;
import org.infinitest.swingui.SwingEventQueue;
import org.infinitest.util.InfinitestUtils;

/**
 * An automated test runner for JUnit Tests.
 *
 * @author <a href="mailto:benrady@gmail.com"Ben Rady</a>
 */
public class InfinitestPresenter implements PropertyChangeListener, TestQueueListener {
  private InfinitestView view;
  private StateMonitor monitor;
  private ResultCollector resultCollector;

  public InfinitestPresenter(ResultCollector resultCollector, InfinitestCore core, InfinitestView infinitestView,
                             TestControl control) {
    this.resultCollector = resultCollector;
    view = infinitestView;
    resultCollector.addStatusChangeListener(this);
    core.addTestQueueListener(this);
    view.addAction(new ReloadIndexAction(core));
    view.addAction(new HaltTestAction(control));
    monitor = new StateMonitor();
    resultCollector.addStatusChangeListener(monitor);
    updateStatus();
  }

  public void propertyChange(final PropertyChangeEvent event) {
    Runnable runnable = new Runnable() {
      public void run() {
        handlePropertyChange(event);
      }
    };
    new SwingEventQueue().pushAndWait(runnable);
  }

  public void testQueueUpdated(TestQueueEvent event) {
    view.setMaximumProgress(event.getInitialSize());
    view.setProgress(1 + event.getTestsRun());
    if (!event.getTestQueue().isEmpty())
      view.setCurrentTest(event.getCurrentTest());
  }

  private void handlePropertyChange(PropertyChangeEvent event) {
    String propertyName = event.getPropertyName();
    if (propertyName.equals(STATUS_PROPERTY))
    {
      Status status = (Status) event.getNewValue();
      updateView(status);
    }
  }

  private void updateView(Status status) {
    view.setStatusMessage(status.toString());
    switch (status)
    {
      case RUNNING:
        view.setProgressBarColor(getUnknownColor());
        break;
      case FAILING:
        view.setProgressBarColor(getFailingColor());
        view.setProgress(view.getMaximumProgress());
        view.setCurrentTest("");
        break;
      case PASSING:
        view.setProgressBarColor(getPassingColor());
        view.setProgress(view.getMaximumProgress());
        view.setCurrentTest("");
        break;
      case INDEXING:
        view.setProgressBarColor(getUnknownColor());
        view.setProgress(view.getMaximumProgress());
        break;
      case SCANNING:
        // No additional updates needed
        break;
    }
  }

  public void updateStatus() {
    long cycleTime = monitor.getCycleLengthInMillis();
    String timeStamp = InfinitestUtils.formatTime(cycleTime);
    view.setAngerBasedOnTime(cycleTime);
    view.setCycleTime(timeStamp);
    view.setStatusMessage(resultCollector.getStatus().getStatusMessage());
  }

  public void reloading() {
  }

  public static Color getPassingColor() {
    return new Color(0x359b35);
  }

  public static Color getFailingColor() {
    return RED;
  }

  public static Color getUnknownColor() {
    return YELLOW;
  }

  public void updateComplete(){
  }
}
